package com.chuangjiangx.member.stored.ddd.domain.model;


import com.chuangjiangx.dddbase.Repository;
import com.chuangjiangx.member.stored.dao.mapper.InMbrStoredStreamMapper;
import com.chuangjiangx.member.stored.dao.model.InMbrStoredStream;
import com.chuangjiangx.member.stored.dao.model.InMbrStoredStreamExample;
import com.chuangjiangx.member.basic.ddd.domain.model.MbrStoredStreamId;
import com.chuangjiangx.member.basic.ddd.domain.model.MemberId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;
import java.util.Optional;

/**
 * 会员储值流水
 *
 * @author cj-ch
 * @date 2018/1/27 下午6:49
 */
@Component
public class MbrStoredStreamRepository implements Repository<MbrStoredStream, MbrStoredStreamId> {

    @Autowired
    private InMbrStoredStreamMapper inMbrStoredStreamMapper;

    @Override
    public MbrStoredStream fromId(MbrStoredStreamId mbrStoredStreamId) {
        InMbrStoredStream inMbrStoredStream = inMbrStoredStreamMapper.selectByPrimaryKey(mbrStoredStreamId.getId());
        return wrap(inMbrStoredStream);
    }

    /**
     * 根据pid查询
     * @return
     */
    @Deprecated
    public MbrStoredStream fromPid(Long pid) {
        InMbrStoredStreamExample example = new InMbrStoredStreamExample();
        InMbrStoredStreamExample.Criteria criteria = example.createCriteria();
        criteria.andTypeEqualTo(MbrStoredType.RECHARGE_GIFT.value);

        criteria.andPidEqualTo(pid);
        List<InMbrStoredStream> inMbrStoredStreams = inMbrStoredStreamMapper.selectByExample(example);
        return inMbrStoredStreams.isEmpty() ? null : wrap(inMbrStoredStreams.get(0));
    }

    /**
     * 根据会员订单Id查询
     * @param mbrOrderId
     * @param type
     * @return
     */
    public MbrStoredStream from(Long mbrOrderId, MbrStoredType type) {
        InMbrStoredStreamExample example = new InMbrStoredStreamExample();
        InMbrStoredStreamExample.Criteria criteria = example.createCriteria();
        criteria.andTypeEqualTo(type.value);
        criteria.andMbrOrderIdEqualTo(mbrOrderId);
        List<InMbrStoredStream> inMbrStoredStreams = inMbrStoredStreamMapper.selectByExample(example);
        return inMbrStoredStreams.isEmpty() ? null : wrap(inMbrStoredStreams.get(0));
    }

    public MbrStoredStream fromMbrRefundId(Long mbrRefundId, MbrStoredType type) {
        InMbrStoredStreamExample example = new InMbrStoredStreamExample();
        InMbrStoredStreamExample.Criteria criteria = example.createCriteria();
        criteria.andTypeEqualTo(type.value);
        criteria.andMbrRefundIdEqualTo(mbrRefundId);
        List<InMbrStoredStream> inMbrStoredStreams = inMbrStoredStreamMapper.selectByExample(example);
        return inMbrStoredStreams.isEmpty() ? null : wrap(inMbrStoredStreams.get(0));
    }

    @Override
    public void update(MbrStoredStream mbrStoredStream) {
        InMbrStoredStream in = unbox(mbrStoredStream);
        in.setUpdateTime(new Date());
        inMbrStoredStreamMapper.updateByPrimaryKeySelective(in);
    }

    @Override
    public void save(MbrStoredStream mbrStoredStream) {
        InMbrStoredStream in = unbox(mbrStoredStream);
        in.setCreateTime(new Date());
        inMbrStoredStreamMapper.insertSelective(in);
        mbrStoredStream.setId(new MbrStoredStreamId(in.getId()));
    }

    private InMbrStoredStream unbox(MbrStoredStream mbrStoredStream) {
        InMbrStoredStream in = new InMbrStoredStream();
        Optional<MbrStoredStream> optional = Optional.ofNullable(mbrStoredStream);
        in.setId(optional.map(o -> o.getId()).map(o -> o.getId()).orElse(null));
        in.setAmount(mbrStoredStream.getAmount());
        in.setMemberId(optional.map(o -> o.getMemberId()).map(o -> o.getId()).orElse(null));
        in.setPid(mbrStoredStream.getPid());
        in.setPostTradingBalance(mbrStoredStream.getPostTradingBalance());
        in.setRemark(mbrStoredStream.getRemark());
        in.setType(mbrStoredStream.getType().value);
        in.setMbrOrderId(optional.map(MbrStoredStream::getMbrOrderId).map(MbrOrderId::getId).orElse(null));
        in.setMbrRefundId(optional.map(MbrStoredStream::getMbrOrderRefundId).map(MbrOrderRefundId::getId).orElse(null));
        in.setMerchantUserId(mbrStoredStream.getMerchantUserId());
        in.setStoreUserId(mbrStoredStream.getStoreUserId());
        in.setStoreId(mbrStoredStream.getStoreId());
        return in;
    }

    private MbrStoredStream wrap(InMbrStoredStream in) {
        MbrStoredStream domain = new MbrStoredStream(
                new MemberId(in.getMemberId()),
                in.getAmount(),
                in.getPostTradingBalance(),
                in.getType() == null ? null : MbrStoredType.getStoredType(in.getType()),
                in.getPid(),
                in.getRemark(),
                null == in.getMbrOrderId() ? null : new MbrOrderId(in.getMbrOrderId()),
                null == in.getMbrRefundId() ? null : new MbrOrderRefundId(in.getMbrRefundId()),
                in.getMerchantUserId(),
                in.getStoreUserId(),
                in.getStoreId()
        );
        if (null != in.getId()) {
            domain.setId(new MbrStoredStreamId(in.getId()));
        }
        return domain;
    }




    public void deleteByMemberId(Long memberId) {
        InMbrStoredStreamExample example = new InMbrStoredStreamExample();
        example.createCriteria().andMemberIdEqualTo(memberId);
        List<InMbrStoredStream> list = example == null ? null : inMbrStoredStreamMapper.selectByExample(example);
        if (list != null && list.size() > 0) {
            list.forEach(inMbrStoredStream -> {
                inMbrStoredStreamMapper.deleteByPrimaryKey(inMbrStoredStream.getId());
            });
        } else {
            return;
        }
    }
}
